Skip to content

fix: handle property names with percent signs in JSON Pointers#2828

Open
chatman-media wants to merge 1 commit into
openapi-ts:mainfrom
chatman-media:fix/percent-sign-property-name
Open

fix: handle property names with percent signs in JSON Pointers#2828
chatman-media wants to merge 1 commit into
openapi-ts:mainfrom
chatman-media:fix/percent-sign-property-name

Conversation

@chatman-media

Copy link
Copy Markdown

Changes

Fixes #2251.

A schema property name containing a literal percent sign (e.g. "25%") crashes codegen with URIError: URI malformed whenever that property resolves to an object:

components:
  schemas:
    response:
      type: object
      properties:
        "25%":
          type: object
          properties:
            color:
              type: string

Root cause

createRef builds JSON Pointer paths by escaping each segment with Redocly's escapePointer, which escapes ~ and / but does not percent-encode. When a nested object is transformed, the accumulated path (e.g. #/components/schemas/response/25%) is fed back into parseRef, whose unescapePointer runs decodeURIComponent on each segment. decodeURIComponent("25%") throws URIError: URI malformed, crashing the whole run.

The same parseRef round-trip is used in several places (createRef, oapiRef, enum-name generation, discriminator property inference), so any of them could hit this with a %-containing key.

Fix

Add a small resilient parseRef wrapper (in src/lib/ts.ts) that delegates to Redocly's parseRef, but on failure falls back to parsing the pointer without decodeURIComponent — and per segment, only decodes when it can, otherwise returns the raw segment. This mirrors the asymmetry of escapePointer (which never percent-encodes), so:

  • Literal % segments (e.g. 25%) pass through unchanged instead of throwing.
  • Legitimately percent-encoded segments (e.g. %7Bid%7D -> {id}) still decode correctly.

All internal parseRef call sites now use this wrapper.

How to Review

  • The behavioral regression test is in test/transform/schema-object/object.test.ts ("property name with percent sign (nested object)"). It throws URIError: URI malformed on main and passes with this change.
  • Unit tests for the wrapper are in test/lib/ts.test.ts (describe("parseRef")): confirms normal parsing, percent-decoding, and no-throw on a bare %.
  • pnpm test passes for the openapi-typescript package.

Checklist

  • Unit tests updated
  • docs/ updated (if necessary) — n/a
  • pnpm run update:examples run — n/a (no example schema output changes)
  • Changeset added (.changeset/percent-sign-property-name.md)

A schema property name containing a literal percent sign (e.g. "25%")
crashed codegen with "URIError: URI malformed" whenever the property
resolved to an object, because the accumulated path was re-parsed through
Redocly's parseRef -> decodeURIComponent.

Wrap parseRef so a failed decodeURIComponent falls back to the raw,
un-decoded pointer segment (mirroring escapePointer, which does not
percent-encode). Valid percent-encoded segments still decode correctly.

Closes openapi-ts#2251
@chatman-media chatman-media requested a review from a team as a code owner June 13, 2026 15:34
@changeset-bot

changeset-bot Bot commented Jun 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 63b2f98

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openapi-typescript Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify

netlify Bot commented Jun 13, 2026

Copy link
Copy Markdown

👷 Deploy request for openapi-ts pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 63b2f98

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process crashes if the schemas has an object type with a key containing a % sign

1 participant